package com.wangshuqi.jdbc.preparedStatement.batch;

import com.wangshuqi.jdbc.util.JDBCUtil;
import org.junit.Test;

import java.sql.Connection;
import java.sql.PreparedStatement;

/**
 * jdbc批量处理
 * 需要更换mysql驱动包为 5.1.37及以上版本
 * CREATE TABLE goods(
 * `id` INT(10) PRIMARY KEY AUTO_INCREMENT ,
 * `name` VARCHAR(25) DEFAULT NULL
 * )CHARSET=utf8
 *
 * @author codewsq
 * @date 2021/8/24 0024 9:34
 */
public class PreparedStatementBatchTest {

    /*
     * 批量处理 方式一：
     * */
    @Test
    public void test() {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            connection = JDBCUtil.getConnection();

            long start = System.currentTimeMillis();
            String sql = "insert into goods(name) values (?)";
            preparedStatement = connection.prepareStatement(sql);
            for (int i = 0; i < 1000000; i++) {
                preparedStatement.setString(1, "name_" + i);
                preparedStatement.execute();
            }
            long end = System.currentTimeMillis();
            System.out.println("操作时间：" + (end - start)); // 操作时间：916878 --> 91秒多
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.closeConnection(connection, preparedStatement);
        }
    }

    /*
     * 方式二：
     *   1. 使用 addBatch() / executeBatch() / clearBatch() 批处理
     *   2. mysql服务器默认是关闭批处理的，我们需要通过一个参数，让mysql开启批处理的支持。
     *          ?rewriteBatchedStatements=true 写在配置文件的url后面，否则批处理不生效
     *   3. 使用更新的mysql 驱动：mysql-connector-java-5.1.37-bin.jar
     * */
    @Test
    public void test2() {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            connection = JDBCUtil.getConnection();

            long start = System.currentTimeMillis();
            String sql = "insert into goods(name) values (?)";
            preparedStatement = connection.prepareStatement(sql);
            for (int i = 0; i < 1000000; i++) {
                preparedStatement.setString(1, "name_" + i);
                // 1.添加至批处理
                preparedStatement.addBatch();
                if (i % 500 == 0 || i == (1000000 - 1)) { // 每2000条执行一次 / 每500条执行一次
                    // 2.执行批处理的sql
                    preparedStatement.executeBatch();
                    // 3.清空批处理
                    preparedStatement.clearBatch();
                }

            }
            long end = System.currentTimeMillis();
            // 每2000条执行一次 操作时间：5112
            // 每500条执行一次  操作时间：7181
            System.out.println("操作时间：" + (end - start));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.closeConnection(connection, preparedStatement);
        }
    }

    /*
     * 方式三：在使用批处理方式的基础之上，使用Connection 的 setAutoCommit(false) 和 commit()
     * */
    @Test
    public void test3() {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            connection = JDBCUtil.getConnection();
            long start = System.currentTimeMillis();
            // 1.设置mysql不自动提交数据
            connection.setAutoCommit(false);
            String sql = "insert into goods(name) values (?)";
            preparedStatement = connection.prepareStatement(sql);
            for (int i = 0; i < 1000000; i++) {
                preparedStatement.setString(1, "name_" + i);
                preparedStatement.addBatch();
                if (i % 2000 == 0 || i == (1000000 - 1)) { // 每2000条执行一次
                    preparedStatement.executeBatch();
                    preparedStatement.clearBatch();
                }
            }
            // 2.提交数据
            connection.commit();
            long end = System.currentTimeMillis();
            System.out.println("操作时间：" + (end - start)); // 操作时间：3712
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.closeConnection(connection, preparedStatement);
        }
    }
}
